package cn.iocoder.yudao.framework.util;

import cn.hutool.extra.spring.SpringUtil;
import jakarta.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.concurrent.Callable;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  使用编程式事务代替声明式事务，避免{@link Transactional}用法不当带来的问题
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2024/12/15
 */
@Slf4j
@Component
public class TransactionUtils {

    private TransactionUtils() {
        super();
    }

    /**
     * 数据库事务提交及回滚
     */
    @Nullable
    public static <R> R transactional(Callable<R> callable) {
        PlatformTransactionManager transactionManager = SpringUtil.getBean(PlatformTransactionManager.class);
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            R result = callable.call();
            transactionManager.commit(status);
            return result;
        } catch (Exception e) {
            transactionManager.rollback(status);
            log.error("业务异常触发事务回滚", e);
            return null;
        }
    }

    /**
     * 在数据库事务提交之后执行
     */
    public static void afterCommit(Callable<Void> callable) {
        try {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    try {
                        callable.call();
                    } catch (Exception e) {
                        log.error("业务异常", e);
                    }
                }
            });
        } catch (Exception e) {
            log.error("TransactionSynchronizationManager.registerSynchronization 执行出错", e);
        }
    }

    /**
     * 在数据库事务提交/回滚之后执行
     */
    public static void afterCompletion(Callable<Void> callable) {
        try {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCompletion(int status) {
                    try {
                        callable.call();
                    } catch (Exception e) {
                        log.error("业务异常", e);
                    }
                }
            });
        } catch (Exception e) {
            log.error("TransactionSynchronizationManager.registerSynchronization 执行出错", e);
        }
    }

}
